package br.com.velp.sudecap.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.sql.Connection;
import java.util.*;
import javax.faces.context.FacesContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;

/**
 * <sumario>
 * <objetivo> "Rastreabilidade" </objetivo>
 * <autor> EDUARDO SANTOS DE OLIVEIRA </autor>
 * <versao>1.0.0.0</versao>
 * <data_criacao> 17.10.2012 </data_criacao>
 * <data_ultima_alteracao> 30.04.2013 </data_ultima_alteracao>
 * <descricao> Classe Utilitária Para Geração de Relatórios/Impressos JASPER </descricao>
 * </sumario>
 */
public class JasperUtil {

    private static final String TIMEZONE = "REPORT_TIME_ZONE";
    private static final String TIMEZONE_BRASIL = "America/Sao_Paulo";
    private static final String LOCALE = "REPORT_LOCALE";
    private static final String MIMETYPE_PDF = "application/pdf";
    private static final String MIMETYPE_XLS = "application/excel";

    /**
     * 
     * Repsonsável Pela Geração e Download do Arquivo PDF, Com Base Em Um Arquivo
     * Jasper
     * 
     * @param String resource (caminho do arquivo JASPER)
     * @param String nomeArquivoSaida (nom do arquivo PDF a ser gerado)
     * @param Collection valores (coleção de valores a serem utilizados pelo relatório)
     * @param HashMap parametros (mapa contendo parâmetros a serem utilizados pelo relatório)
     * 
     */
    public static void gerarArquivoPDF(String resource, String nomeArquivoSaida, Collection valores, HashMap parametros) {
        
        Date dataAtual = new Date();
        
        if (!nomeArquivoSaida.contains(".pdf")) {
            nomeArquivoSaida += "_".concat(String.valueOf(dataAtual.getTime()));
            nomeArquivoSaida += ".pdf";
        } else {
            nomeArquivoSaida.replaceAll(".pdf", "");
            nomeArquivoSaida += "_".concat(String.valueOf(dataAtual.getTime()));
            nomeArquivoSaida += ".pdf";
        }

        if (parametros == null) {
            parametros = new HashMap();
        }

        gerarArquivoDownload(new JRPdfExporter(), parametros, nomeArquivoSaida, MIMETYPE_PDF, resource, valores, null);

    }

    /**
     * 
     * Repsonsável Pela Geração e Download do Arquivo PDF, Com Base Em Um Arquivo
     * Jasper
     * 
     * @param String resource (caminho do arquivo JASPER)
     * @param String nomeArquivoSaida (nom do arquivo PDF a ser gerado)
     * @param Connection conn (conexão JDBC a ser utilizada como DataSource do Relatório)
     * @param HashMap parametros (mapa contendo parâmetros a serem utilizados pelo relatório)
     * 
     */
    public static void gerarArquivoPDF(String resource, String nomeArquivoSaida, Connection conn, HashMap parametros) {

        Date dataAtual = new Date();
        
        if (!nomeArquivoSaida.contains(".pdf")) {
            nomeArquivoSaida += "_".concat(String.valueOf(dataAtual.getTime()));
            nomeArquivoSaida += ".pdf";
        } else {
            nomeArquivoSaida.replaceAll(".pdf", "");
            nomeArquivoSaida += "_".concat(String.valueOf(dataAtual.getTime()));
            nomeArquivoSaida += ".pdf";
        }

        if (parametros == null) {
            parametros = new HashMap();
        }
        
        gerarArquivoDownload(new JRPdfExporter(), parametros, nomeArquivoSaida, MIMETYPE_PDF, resource, null, conn);

    }
    
    /**
     * 
     * Repsonsável Pela Geração e Download do Arquivo XLS, Com Base Em Um Arquivo
     * Jasper
     * 
     * @param String resource (caminho do arquivo JASPER)
     * @param String nomeArquivoSaida (nom do arquivo XLS a ser gerado)
     * @param Collection valores (coleção de valores a serem utilizados pelo relatório)
     * @param HashMap parametros (mapa contendo parâmetros a serem utilizados pelo relatório)
     * 
     */    
    public static void gerarArquivoXLS(String resource, String nomeArquivoSaida, Collection valores, HashMap parametros) {

        Date dataAtual = new Date();
        
        if (!nomeArquivoSaida.contains(".xls")) {
            nomeArquivoSaida += "_".concat(String.valueOf(dataAtual.getTime()));
            nomeArquivoSaida += ".xls";
        } else {
            nomeArquivoSaida.replaceAll(".xls", "");
            nomeArquivoSaida += "_".concat(String.valueOf(dataAtual.getTime()));
            nomeArquivoSaida += ".xls";
        }
        
        if (parametros == null) {
            parametros = new HashMap();
        }

        gerarArquivoDownload(getExporterXLSReport(), parametros, nomeArquivoSaida, MIMETYPE_XLS, resource, valores, null);

    }
    
    /**
     * 
     * Repsonsável Pela Geração e Download do Arquivo XLS, Com Base Em Um Arquivo
     * Jasper
     * 
     * @param String resource (caminho do arquivo JASPER)
     * @param String nomeArquivoSaida (nom do arquivo XLS a ser gerado)
     * @param Collection valores (coleção de valores a serem utilizados pelo relatório)
     * @param HashMap parametros (mapa contendo parâmetros a serem utilizados pelo relatório)
     * 
     */    
    public static void gerarArquivoXLS(String resource, String nomeArquivoSaida, Collection valores, HashMap parametros, JRExporter exporter) {

        Date dataAtual = new Date();
        
        if (!nomeArquivoSaida.contains(".xls")) {
            nomeArquivoSaida += "_".concat(String.valueOf(dataAtual.getTime()));
            nomeArquivoSaida += ".xls";
        } else {
            nomeArquivoSaida.replaceAll(".xls", "");
            nomeArquivoSaida += "_".concat(String.valueOf(dataAtual.getTime()));
            nomeArquivoSaida += ".xls";
        }

        if (parametros == null) {
            parametros = new HashMap();
        }

        gerarArquivoDownload(exporter, parametros, nomeArquivoSaida, MIMETYPE_XLS, resource, valores, null);

    }
    
    /**
     * 
     * Repsonsável Pela Geração e Download do Arquivo XLS, Com Base Em Um Arquivo
     * Jasper
     * 
     * @param String resource (caminho do arquivo JASPER)
     * @param String nomeArquivoSaida (nom do arquivo XLS a ser gerado)
     * @param Connection conn (conexão JDBC para execução da consulta pelo relatório)
     * @param HashMap parametros (mapa contendo parâmetros a serem utilizados pelo relatório)
     * 
     */    
    public static void gerarArquivoXLS(String resource, String nomeArquivoSaida, Connection conn, HashMap parametros) {
        
        Date dataAtual = new Date();
        
        if (!nomeArquivoSaida.contains(".xls")) {
            nomeArquivoSaida += "_".concat(String.valueOf(dataAtual.getTime()));
            nomeArquivoSaida += ".xls";
        } else {
            nomeArquivoSaida.replaceAll(".xls", "");
            nomeArquivoSaida += "_".concat(String.valueOf(dataAtual.getTime()));
            nomeArquivoSaida += ".xls";
        }

        if (parametros == null) {
            parametros = new HashMap();
        }

        gerarArquivoDownload(getExporterXLSReport(), parametros, nomeArquivoSaida, MIMETYPE_XLS, resource, null, conn);

    }
    
    /**
     * Opções Para Configuração de Exportação do Report Para Excel - Exportação dos Grids de Pesquisa
     * @return JRExporter exporterXLS
     */
    public static JRExporter getExporterXLSPadrao(){
        
        JRExporter exporter = new JRXlsExporter();
        exporter.setParameter(JRXlsExporterParameter.CHARACTER_ENCODING, "UTF-8");
        exporter.setParameter(JRXlsExporterParameter.IGNORE_PAGE_MARGINS, Boolean.TRUE);
        exporter.setParameter(JRXlsExporterParameter.IS_FONT_SIZE_FIX_ENABLED, Boolean.TRUE);
        exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.TRUE);
        exporter.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
        exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
        exporter.setParameter(JRXlsExporterParameter.IS_IGNORE_CELL_BORDER, Boolean.FALSE);

        return exporter;
        
    }

    /**
     * Opções Para Configuração de Exportação do Report Para Excel - Exportação dos Relatórios
     * @return JRExporter exporterXLS
     */
    public static JRExporter getExporterXLSReport(){
        
        JRExporter exporter = new JRXlsExporter();

        exporter.setParameter(JRXlsExporterParameter.CHARACTER_ENCODING, "UTF-8");
        exporter.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
        exporter.setParameter(JRXlsExporterParameter.IS_IGNORE_CELL_BORDER, Boolean.FALSE);
        exporter.setParameter(JRXlsExporterParameter.IS_FONT_SIZE_FIX_ENABLED, Boolean.TRUE);
        exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
        exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_COLUMNS, Boolean.TRUE);
        exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.TRUE);
        exporter.setParameter(JRXlsExporterParameter.CREATE_CUSTOM_PALETTE, Boolean.TRUE);
        
        return exporter;
        
    }
    
    /**
     * 
     * Responsável Pela Geração do Arquivo PDF Em Disco
     * 
     * @param Map<String, Object> params
     * @param String reportPath
     * @param String destinyFile
     * @param Object.. values
     * @return File arquivoGerado
     * 
     * @throws JRException 
     * 
     */
    public static File gerarPdfEmDisco(HashMap<String, Object> params, String jrxmlReportPath, String destinyFile, Object... values) {
        
        try {
            
            String realPathReport = JsfUtil.getRealPath(jrxmlReportPath); 

            JasperReport jasperReport = JasperCompileManager.compileReport(realPathReport);
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, new JRBeanCollectionDataSource(Arrays.asList(values)));
            JasperExportManager.exportReportToPdfFile(jasperPrint, destinyFile);

            return new File(destinyFile);
            
        } catch (Exception ex) {
            
            MensagemUtil.exibirMensagemErro(ex.toString());
            return null;
            
        }
        
    }
    
    /**
     * 
     * Parâmetros Comuns Utilizados Pela Maioria dos Relatórios 
     * do Sistema
     * 
     * @return HashMap<String, Object> parametrosPadrao
     * 
     */
    public static HashMap<String, Object> getParametrosPadrao() {
        
        HashMap<String, Object> params = new HashMap<String, Object>();
        
        params.put("LOGO_PBH", JsfUtil.getRealPath("/resources/imagens/logo_pbh.jpg"));
        params.put("LOGO_SUDECAP", JsfUtil.getRealPath("/resources/imagens/sudecap.jpg"));
        params.put("CABECALHO_DIR", JsfUtil.getRealPath("/relatorios").concat(File.separator));                    
        params.put("REPORT_LOCALE", new Locale("pt", "BR"));
        params.put("REPORT_TIME_ZONE", TimeZone.getTimeZone("America/Sao_Paulo"));
        
        return params;
        
    }
    
    /**
     * 
     * Responsável Pela Geração do Arquivo de Saída do Relatório JASPER
     * 
     * @param JRExporter exporter (interface responsável pela definição do tipo de arquivo de saída)
     * @param HashMap parametros (parâmetros a serem utilizados pelo relatório)
     * @param String nomeArquivoSaida (nome do arquivo de saída gerado através do Jasper)
     * @param String mimeType (define o tipo de arquivo a ser baixado pelo browser)
     * @param String resource (caminho de localização do arquivo fonte JASPER)
     * @param Collection valores (coleção de valores a serem utilizados pelo relatório)
     * 
     */
    private static void gerarArquivoDownload(JRExporter exporter, HashMap parametros, String nomeArquivoSaida,
            String mimeType, String resource, Collection valores, Connection conn) {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        facesContext.responseComplete();
        
        if (parametros != null) {
            parametros.put(TIMEZONE, java.util.TimeZone.getTimeZone(TIMEZONE_BRASIL));
            parametros.put(LOCALE, new Locale("pt", "BR"));
        }
        
        try {
                            
            String caminhoRelatorio = JsfUtil.getRealPath(resource);  
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            if (valores != null){
                exporter.setParameter(JRXlsExporterParameter.JASPER_PRINT, JasperFillManager.fillReport(caminhoRelatorio, parametros, new JRBeanCollectionDataSource(valores)));
            }else {
                exporter.setParameter(JRXlsExporterParameter.JASPER_PRINT, JasperFillManager.fillReport(caminhoRelatorio, parametros, conn));
            }
            
            exporter.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, baos);
            exporter.exportReport();

            byte[] bytes = baos.toByteArray();

            if (bytes != null && bytes.length > 0) {
                
                HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
                response.setContentType(mimeType);
                response.setHeader("Content-disposition", "attachment; filename=\"" + nomeArquivoSaida + "\"");
                response.setContentLength(bytes.length);
                
                ServletOutputStream outputStream = response.getOutputStream();
                outputStream.write(bytes, 0, bytes.length);
                
                outputStream.flush();
                outputStream.close();
                
            }

        } catch (Exception e) {

            e.printStackTrace();
            MensagemUtil.exibirMensagemErro(e.toString());

        }

    }
    
}
